package org.ccay.core.dispatcher;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.ccay.core.exception.ApplicationException;
import org.ccay.core.exception.ExceptionHandler;
import org.ccay.core.ioc.Ccay;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.ILogger;
import org.ccay.core.util.CollectionUtil;

/**
 * 事件Util，用于触发事件，可以根据事件处理器的类型（IEventHandler的派生接口）来分发事件给所有实现了该类型的实现
 * <p/>
 * EventUtil 的使用示例：
 * <pre>
 * <code>
 *	public void testDispatch() throws ApplicationException {
 *		EventArgs1 args1 = new EventArgs1();
 *		args1.setMessage("XXX");
 *		
 *		EventUtil.dispatch(IEventHandler1.class, this, args1,true);
 *	}
 * </code>
 * </pre>
 * 
 */
public final class EventUtil<T extends IEventHandler<E>,E extends IEventArgs> {
	/**
	 * 防止实例
	 */
	private EventUtil(){		
	}
	private static ILogger logger = CcayLoggerFactory.getLogger(EventUtil.class);
	
	
	/** 
	 * 处理事件并忽略错误	
	 * 
	 * @since 2012-6-12
	 * @param handlerClass
	 * @return
	 */
	public static <T extends IEventHandler<E>,E extends IEventArgs> int dispatch(Class<T> handlerClass){
		try {
			return dispatch(handlerClass,null,null,true);
		} catch (Exception e) {
			ExceptionHandler.logException(e);
			return 0;
		}
	}
	/** 
	 * 处理事件并忽略错误
	 * @param handlerClass
	 * @param sender
	 * @param args
	 * @return
	 */
	public static <T extends IEventHandler<E>,E extends IEventArgs> 
		int dispatch(Class<T> handlerClass, Object sender, E args){
		try {
			return dispatch(handlerClass,sender,args,true);
		} catch (Exception e) {
			ExceptionHandler.logException(e);
			return 0;
		}
	}
 
	private static  Map<String,Object> handlersCache = new HashMap<String, Object>();
	/** 
	 * 触发事件
	 * @param handlerClass 处理器类 
	 * @param sender 事件引发者
	 * @param args 事件参数
	 * @param ignoreError 忽略错误
	 * @return 所执行的处理器个数
	 * @throws ApplicationException
	 */
	@SuppressWarnings("unchecked")
	public static <T extends IEventHandler<E>,E extends IEventArgs> 
		int dispatch(Class<T> handlerClass, Object sender, E args, boolean ignoreError)
		throws ApplicationException{
		
		List<T> handlerList ;
		
		//加入缓存
		String handlerName = handlerClass.getName();
		Object cachedHandlers = handlersCache.get(handlerName);
		
		if(cachedHandlers != null){
			handlerList = (List<T>)cachedHandlers;
		}else{
			handlerList = (List<T>) getBeansOfType(handlerClass);
			handlersCache.put(handlerName, handlerList);
		}
		
		if(handlerList == null || handlerList.isEmpty()){
			return 0;
		}
		
		for (IEventHandler<E> handler : handlerList) {
			logger.trace("Before excute event handler: {0}", handlerName );
			if(!ignoreError){
				//非忽略错误模式，直接执行
				handler.execute(sender, args);
				continue;
			}
			//忽略错误，则发生错误时仅记录日志
			try{
				handler.execute(sender, args);
			}catch(Exception ex){
				ExceptionHandler.logException(ex);
			}
		}
		return handlerList.size();
	}
	@SuppressWarnings("unchecked")
	private static <T> List<T> getBeansOfType(Class<T>  handlerClass){
		List<T> handlerList  = null;
		Map<String, T> handlerMap =  Ccay.getContext().getBeansOfType(handlerClass);
		handlerList  = (List<T>) CollectionUtil.convertList((Map<String, Object>) handlerMap);
		//有排序的规则
		if(IOrder.class.isAssignableFrom(handlerClass) ){
			List<IOrder> handlerOrderList = (List<IOrder>) handlerList;
			Collections.sort(handlerOrderList, new Comparator<IOrder>(){ 
				public int compare(IOrder o1, IOrder o2) {
					return o1.getOrder() - o2.getOrder();
				}			
			});
			handlerList = (List<T>) handlerOrderList;
		}
		return handlerList;
	}
}
